package com.ruoyi.keep.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;


import com.ruoyi.keep.domain.Teacher;
import com.ruoyi.keep.mapper.TeacherMapper;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.keep.mapper.FitnessGymMapper;
import com.ruoyi.keep.domain.FitnessGym;
import com.ruoyi.keep.service.IFitnessGymService;

/**
 * 健身馆Service业务层处理
 *
 * @author zqd
 * @date 2024-08-14
 */
@Service
public class FitnessGymServiceImpl implements IFitnessGymService {
    @Autowired
    private FitnessGymMapper fitnessGymMapper;
    @Autowired
    public RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    public RedisTemplate<String, FitnessGym> redisTemplate2;
    @Autowired
    public RedisTemplate<String, Object> redisTemplate3;


    /**
     * 查询健身馆
     *
     * @param id 健身馆主键
     * @return 健身馆
     */
    @Override
    public FitnessGym selectFitnessGymById(Long id) {
        return fitnessGymMapper.selectFitnessGymById(id);
    }

    /**
     * 查询健身馆列表
     *
     * @param fitnessGym 健身馆
     * @return 健身馆
     */

    public List<FitnessGym> selectFitnessGymList(FitnessGym fitnessGym) {
        // 查询所有老师
        List<FitnessGym> fitnessGyms = fitnessGymMapper.selectFitnessGymList(fitnessGym);
        return fitnessGyms;

    }
    /**
     * 新增健身馆
     *
     * @param fitnessGym 健身馆
     * @return 结果
     */
    @Override
    public int insertFitnessGym(FitnessGym fitnessGym) {
        int gym = fitnessGymMapper.insertFitnessGym(fitnessGym);
//1、新增的时候把场馆信息存入缓存,
//键:（自定义字符串+新增这个场馆id）值:是场馆对象，因为会把对象所有信息存进缓存
        redisTemplate2.opsForValue().set("gym" + fitnessGym.getId(), fitnessGym);
        fitnessGym.setId(fitnessGym.getId());
        //2、设置经纬度，把场馆经纬度存入位置缓存
        Point point = new Point(fitnessGym.getLongitude(), fitnessGym.getLatitude());
//        把id转为字符串类型
        String id = String.valueOf(fitnessGym.getId());
//经纬度和场馆名存入缓存
        redisTemplate3.opsForGeo().geoAdd("geospatial", point, "gym" + id);
        return gym;
    }
    //把用户经纬度一起存位置缓存
    @Override
    public List<FitnessGym> insertuserRedis(Double longitude, Double latitude, Integer userid) {
        Point point = new Point(longitude, latitude);
//1、用户经纬度和id存入缓存
        redisTemplate3.opsForGeo().geoAdd("geospatial", point, "user" + userid);
//2、查询用户10000米内所有场馆距离
        GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate3.opsForGeo().radius("geospatial", new Circle(point, new Distance(20000, Metrics.KILOMETERS)), RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance());

        // 3、如果缓存清空，重新从数据库查询存入缓存重新计算
        results.getContent().forEach(result -> {
            RedisGeoCommands.GeoLocation<Object> geoLocation = result.getContent();
            System.out.println("==================111111111111111111");
            System.out.println(geoLocation.getPoint());
            if ( geoLocation.getPoint() == null) {
                List<FitnessGym> fitnessGyms = fitnessGymMapper.selectFitnessGymList(null);
                for (FitnessGym fitnessGym : fitnessGyms) {
                    redisTemplate2.opsForValue().set("gym" + fitnessGym.getId(), fitnessGym);
                    //2、设置经纬度，把场馆经纬度存入位置缓存
                    Point point1 = new Point(fitnessGym.getLongitude(), fitnessGym.getLatitude());
//        把id转为字符串类型
                    String id = String.valueOf(fitnessGym.getId());
//经纬度和场馆名存入缓存
                    redisTemplate3.opsForGeo().geoAdd("geospatial", point1, "gym" + id);
                }
                // 重新查询
            }
        });
        results=  redisTemplate3.opsForGeo().radius("geospatial", new Circle(point, new Distance(20000, Metrics.KILOMETERS)), RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance());
        ArrayList<FitnessGym> list = new ArrayList<>();
        // 遍历查询结果
        results.getContent().forEach(result -> {
            RedisGeoCommands.GeoLocation<Object> geoLocation = result.getContent();
//  查到的两千米内成员名字
            String gymid = (String) geoLocation.getName();
//            距离
            double distances = result.getDistance().getValue();
            //把距离保留一位小数
            BigDecimal number = new BigDecimal(distances);
            BigDecimal distance = number.setScale(1, RoundingMode.HALF_UP);
//通过场馆key查到整个对象信息
            FitnessGym fitnessGym = redisTemplate2.opsForValue().get(gymid);
            if (fitnessGym == null) {
                System.out.println("haha" + fitnessGym);
            } else {
                FitnessGym gym = new FitnessGym();
                //健身馆名字
                gym.setGymName(fitnessGym.getGymName());
//                距离
                gym.setDistance(distance);
//                电话
                gym.setPhone(fitnessGym.getPhone());
//                地址
                gym.setLocation(fitnessGym.getLocation());
//                图片
                gym.setPicture(fitnessGym.getPicture());
//                状态
                gym.setState(fitnessGym.getState());
//                介绍
                gym.setGymIntro(fitnessGym.getGymIntro());
//                邮箱
                gym.setEmail(fitnessGym.getEmail());
//                键
                gym.setGymid(gymid);
//                评分
                gym.setScore(fitnessGym.getScore());
//                介绍
                gym.setGymIntro(fitnessGym.getGymIntro());
//               更新后的对象覆盖存入redis
                redisTemplate2.opsForValue().set("gym" + fitnessGym.getId(), gym);
//                存入集合返回出去，也可以直接缓存中拿
                list.add(gym);

            }
        });
        return list;
    }
//    通过缓存key查询健身馆
    @Override
    public FitnessGym selectgynmidRedis(String gymid) {
        FitnessGym fitnessGym = redisTemplate2.opsForValue().get(gymid);
        return fitnessGym;
    }

    //通过名字模糊查询健身馆
    @Override
    public List<FitnessGym> selectByname(String gymName) {
//弄个容器从缓存查装返回出去的东西
        List<FitnessGym> fitnessGyms = new ArrayList<>();
//从数据库模糊查询，符合名字的名字和id  ，存进这个list
        List<FitnessGym> list  = fitnessGymMapper.selectBynameList(gymName);
//遍历这个list拿到所有符合的对象
        for (FitnessGym fitnessGym : list) {
//通过对象得到id
            Long id = fitnessGym.getId();
//id拼接gym得到键值去数据库查询
            FitnessGym fitnessGym1 = redisTemplate2.opsForValue().get("gym"+id.toString());
            if (fitnessGym1 == null) {
                System.out.println("缓存中查不到的不存储");
            } else {
                fitnessGyms.add(fitnessGym1);
            }
        }
        return fitnessGyms;
    }


//

    /**
     * 修改健身馆
     *
     * @param fitnessGym 健身馆
     * @return 结果
     */
    @Override
    public int updateFitnessGym(FitnessGym fitnessGym) {
        int gym = fitnessGymMapper.updateFitnessGym(fitnessGym);
        redisTemplate2.opsForValue().set("gym" + fitnessGym.getId(), fitnessGym);
        //2、设置经纬度，把场馆经纬度存入位置缓存
        Point point = new Point(fitnessGym.getLongitude(), fitnessGym.getLatitude());
//        把id转为字符串类型
        String id = String.valueOf(fitnessGym.getId());
//经纬度和场馆名存入缓存
        redisTemplate3.opsForGeo().geoAdd("geospatial", point, "gym" + id);
        return gym;
    }

    /**
     * 批量删除健身馆
     *
     * @param ids 需要删除的健身馆主键
     * @return 结果
     */
    @Override
    public int deleteFitnessGymByIds(Long[] ids) {
//        遍历id把缓存里面的也删除了
        for (Long id: ids) {
            redisTemplate2.opsForValue().getOperations().delete("gym"+id);
        }
        return  fitnessGymMapper.deleteFitnessGymByIds(ids);

    }

    /**
     * 删除健身馆信息
     *
     * @param id 健身馆主键
     * @return 结果
     */
    @Override
    public int deleteFitnessGymById(Long id) {
//        在数据库删除的同时，把缓存里面的也删除了
        redisTemplate2.opsForValue().getOperations().delete("gym"+id);
        return  fitnessGymMapper.deleteFitnessGymById(id);
    }


}
